//PongGeometry.m

#import "PongGeometry.h"

//Slightly modified from From GNUStep core NSGeometry.m
static Class	NSStringClass = 0;
static Class	NSScannerClass = 0;
static SEL	scanFloatSel;
static SEL	scanStringSel;
static SEL	scannerSel;
static BOOL	(*scanFloatImp)(NSScanner*, SEL, float*);
static BOOL	(*scanStringImp)(NSScanner*, SEL, NSString*, NSString**);
static id 	(*scannerImp)(Class, SEL, NSString*);

static inline void
setupCache(void)
{
  if (NSStringClass == 0)
    {
      NSStringClass = [NSString class];
      NSScannerClass = [NSScanner class];
      scanFloatSel = @selector(scanFloat:);
      scanStringSel = @selector(scanString:intoString:);
      scannerSel = @selector(scannerWithString:);
      scanFloatImp = (BOOL (*)(NSScanner*, SEL, float*))
	[NSScannerClass instanceMethodForSelector: scanFloatSel];
      scanStringImp = (BOOL (*)(NSScanner*, SEL, NSString*, NSString**))
	[NSScannerClass instanceMethodForSelector: scanStringSel];
      scannerImp = (id (*)(Class, SEL, NSString*))
	[NSScannerClass methodForSelector: scannerSel];
    }
}

CGPoint
PongCGPointFromString(NSString* string)
{
  NSScanner	*scanner;
  CGPoint	point;

  setupCache();
  scanner = (*scannerImp)(NSScannerClass, scannerSel, string);
  if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"x", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &point.x)
    && (*scanStringImp)(scanner, scanStringSel, @";", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"y", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &point.y)
    && (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
    {
      return point;
    }
  else
    {
      [scanner setScanLocation: 0];
      if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
	&& (*scanFloatImp)(scanner, scanFloatSel, &point.x)
	&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
	&& (*scanFloatImp)(scanner, scanFloatSel, &point.y)
	&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
	{
	  return point;
	}
      else
	{
	  return CGPointMake(0, 0);
	}
    }
}

CGSize
PongCGSizeFromString(NSString* string)
{
  NSScanner	*scanner;
  CGSize	size;

  setupCache();
  scanner = (*scannerImp)(NSScannerClass, scannerSel, string);
  if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"width", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &size.width)
    && (*scanStringImp)(scanner, scanStringSel, @";", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"height", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &size.height)
    && (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
    {
      return size;
    }
  else
    {
      [scanner setScanLocation: 0];
      if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
	&& (*scanFloatImp)(scanner, scanFloatSel, &size.width)
	&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
	&& (*scanFloatImp)(scanner, scanFloatSel, &size.height)
	&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
	{
	  return size;
	}
      else
	{
	  return CGSizeMake(0, 0);
	}
    }
}

CGRect
PongCGRectFromString(NSString* string)
{
  NSScanner	*scanner;
  CGRect	rect;

  setupCache();
  scanner = (*scannerImp)(NSScannerClass, scannerSel, string);
  if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"x", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.x)
    && (*scanStringImp)(scanner, scanStringSel, @";", NULL)

    && (*scanStringImp)(scanner, scanStringSel, @"y", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.y)
    && (*scanStringImp)(scanner, scanStringSel, @";", NULL)

    && (*scanStringImp)(scanner, scanStringSel, @"width", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &rect.size.width)
    && (*scanStringImp)(scanner, scanStringSel, @";", NULL)

    && (*scanStringImp)(scanner, scanStringSel, @"height", NULL)
    && (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
    && (*scanFloatImp)(scanner, scanFloatSel, &rect.size.height)
    && (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
    {
      return rect;
    }
  else
    {
      [scanner setScanLocation: 0];
      if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
	&& (*scanStringImp)(scanner, scanStringSel, @"{", NULL)
	&& (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.x)
	&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)

	&& (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.y)
	&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL)
	&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
	
	&& (*scanStringImp)(scanner, scanStringSel, @"{", NULL)
	&& (*scanFloatImp)(scanner, scanFloatSel, &rect.size.width)
	&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
	
	&& (*scanFloatImp)(scanner, scanFloatSel, &rect.size.height)
	&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL)
	&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
	{
	  return rect;
	}
      else
	{
	  return CGRectMake(0, 0, 0, 0);
	}
    }
}

//Some conversions

NSPoint NSPointFromCGPoint(CGPoint thePoint)
{
       NSPoint retval = NSMakePoint(thePoint.x, thePoint.y);
       return retval;
}

CGPoint CGPointFromNSPoint(NSPoint thePoint)
{
       CGPoint retval = CGPointMake(thePoint.x, thePoint.y);
       return retval;
}

NSRect NSRectFromCGRect(CGRect theRect)
{
       NSRect retval = NSMakeRect(theRect.origin.x, theRect.origin.y, theRect.size.width, theRect.size.height);
       return retval;
}

CGRect CGRectFromNSRect(NSRect theRect)
{
       CGRect retval = CGRectMake(theRect.origin.x, theRect.origin.y, theRect.size.width, theRect.size.height);
       return retval;
}

